from django_redis import get_redis_connection
from rest_framework import serializers

from goods.models import SKU


class PlaceOrderSerializer(serializers.ModelSerializer):
    count = serializers.IntegerField(label='個數')

    class Meta:
        model = SKU
        fields = ['id','name','price','default_image_url','count']


class PlaceSerializer(serializers.Serializer):

    skus = PlaceOrderSerializer(many=True)

    freight = serializers.DecimalField(max_digits=10,decimal_places=2)

# class CarSKUSerializer(serializers.ModelSerializer):
#
#     count = serializers.IntegerField(label='數量')
#
#     class Meta:
#         model = SKU
#         fields = ('id','name','default_image_url','price','count')
#
# class OrderSettlementSerializer(serializers.Serializer):
#
#     freight = serializers.DecimalField(label='運費',max_digits=10,decimal_places=2)
#     skus = CarSKUSerializer(many=True)

from order.models import OrderInfo, OrderGoods


class OrderSerializer(serializers.ModelSerializer):
    class Meta:
        model = OrderInfo
        fields = ('order_id', 'address', 'pay_method')
        read_only_fields = ('order_id',)
        extra_kwargs = {
            'address': {
                'write_only': True,
                'required': True,
            },
            'pay_method': {
                'write_only': True,
                'required': True
            }
        }

    def create(self, validated_data):

        address = validated_data['address']
        pay_method = validated_data['pay_method']
        user = self.context['request'].user

        from django.utils import timezone

        order_id = timezone.now().strftime('%Y%M%d%H%M%S') + '%09d'%user.id

        total_count = 0
        from decimal import Decimal
        total_amount = Decimal('0')
        freight = Decimal('10')


        if pay_method == OrderInfo.PAY_METHODS_ENUM['CASH']:
            status = OrderInfo.ORDER_STATUS_ENUM['UNSEND']
        else:
            status = OrderInfo.ORDER_STATUS_ENUM['UNPAID']

        from django.db import transaction
        with transaction.atomic():

            save_point = transaction.savepoint()

            order = OrderInfo.objects.create(
                order_id = order_id,
                user = user,
                address = address,
                total_count = total_count,
                total_amount = total_amount,
                freight=freight,
                pay_method=pay_method,
                status=status
            )

            redis_conn = get_redis_connection('cart')
            sku_id_counts = redis_conn.hgetall('cart_%s'%user.id)
            selected_ids = redis_conn.smembers('cart_selected_%s'%user.id)

            redis_selected_cart = {}

            for sku_id in selected_ids:
                redis_selected_cart[int(sku_id)]=int(sku_id_counts[sku_id])

            for sku_id,count in redis_selected_cart.items():

                try:
                    sku = SKU.objects.get(pk=sku_id)
                except SKU.DoesNotExist:
                    # 回滾
                    transaction.savepoint_rollback(save_point)
                    raise serializers.ValidationError('商品不存在')
                if sku.stock < count:
                    transaction.savepoint_rollback(save_point)
                    raise serializers.ValidationError('庫存不足')

                # sku.stock -= count
                # sku.sales += count
                # sku.save()

                # import time
                # time.sleep(7)

                old_stock = sku.stock

                new_stock = sku.stock-count
                new_sales = sku.sales+count

                rect  = SKU.objects.filter(pk=sku.id,stock=old_stock).update(stock=new_stock,sales=new_sales)

                if rect == 0:
                    transaction.savepoint_rollback(save_point)
                    raise serializers.ValidationError('下單失敗')

                order.total_count += count
                order.total_amount += (count*sku.price)


                OrderGoods.objects.create(
                   order=order,
                   sku=sku,
                   count=count,
                   price=sku.price
                )
            order.save()

            transaction.savepoint_commit(save_point)

        return order



